package com.hy.study.hdfs;

import org.apache.commons.lang.time.DateFormatUtils;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.*;
import org.apache.log4j.Logger;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.file.Paths;
import java.util.Date;
import java.util.Locale;
import java.util.UUID;

/**
 * java客户端使用hdfs 权限异常2中解决办法 1.在运行时传递 -DHADOOP_USER_NAME=root 2.FileSystem fs = FileSystem.get(new URI("hdfs://123.57.217.217:9000"), conf, "root");
 *
 * @author huyong
 * @date 2024 年 01 月 23 日 17:30: 49
 */
public class HdfsClient {
    private final static Logger log = Logger.getLogger(HdfsClient.class);
    private FileSystem fs = null;
    private String basePath = "/data/file/" + UUID.randomUUID().toString().replaceAll("-", "");

    @Before
    public void before() throws Exception {
        // 1.获取hdfs客户端
        Configuration conf = new Configuration();
        //  conf.set("dfs.client.use.datanode.hostname", "true");
        conf.set("dfs.replication", "1");// 设置副本数为1
        fs = FileSystem.get(new URI("hdfs://127.0.0.1:9000"), conf, "DIGITAL-HUYONG");
    }

    /**
     * 创建文件夹
     *
     * @throws Exception
     */
    @Test
    public void mkdir() throws Exception {
        // 2.在hdfs 上创建路径
        boolean mkdirs = fs.mkdirs(new Path(basePath));
        log.info("创建路径:" + (mkdirs ? "成功" : "失败"));
    }

    /**
     * 文件上传
     */
    @Test
    public void testCopyFromLocalFile() throws Exception {
        fs.copyFromLocalFile(new Path("F:\\Downloads\\FAQ.doc"), new Path(basePath + "FAQ.doc"));
    }

    /**
     * 将集群中的文件下载到本地
     */
    @Test
    public void testCopyToLocalFile() throws IOException {
        fs.copyToLocalFile(new Path("/data/file/8f189175a55f46619f8606b9a6b162b1FAQ.doc"), new Path("F:\\tmp\\temp\\" + getUUID() + ".doc"));
        // 参数1:是否删除远程的文件   参数二:远程的文件路径  参数三:本地保存的路径  参数四: 是否本地模式   非本地模式生成CRC的校验文件 本地模式不生成
        fs.copyToLocalFile(true, new Path("/data/file/8f189175a55f46619f8606b9a6b162b1FAQ.doc"), new Path("F:\\tmp\\temp\\" + getUUID() + ".doc"), true);

    }

    /**
     * 删除
     */
    @Test
    public void testDelete() throws IOException {
        // 参数1 文件路径  参数2:是否递归删除
        boolean delete = fs.delete(new Path("/data/file/"), true);
        // 如果文件存在就删除成功  文件不存在 删除失败
        // boolean delete = fs.deleteOnExit(new Path("/data/file/1ed7c92c340f46f8a3c430fa1bd46572FAQ.doc"));
        log.info("删除 " + (delete ? "成功" : "失败"));
    }

    /**
     * 修改文件的名称
     *
     * @throws IOException
     */

    @Test
    public void testRenameFile() throws IOException {
        boolean rename = fs.rename(new Path("/data/file/b505bb27f1754d6a9709292ba9d39075FAQ.doc"), new Path("/data/file/FAQ.doc"));

        log.info("修改 " + (rename ? "成功" : "失败"));
    }

    /**
     * 文件详情的查看
     *
     * @throws Exception
     */
    @Test
    public void testListFiles() throws Exception {
        RemoteIterator<LocatedFileStatus> locatedFileStatusRemoteIterator = fs.listFiles(new Path("/"), true);
        while (locatedFileStatusRemoteIterator.hasNext()) {
            LocatedFileStatus next = locatedFileStatusRemoteIterator.next();
            log.info(next.getPath().getName());// 获取文件名称
            log.info(next.getPermission());// 获取文件权限
            log.info(next.getLen());// 文件长度
            log.info(next.getBlockSize());// 块大小
            BlockLocation[] blockLocations = next.getBlockLocations();
            for (BlockLocation blockLocation : blockLocations) {// 获取块信息
                String[] hosts = blockLocation.getHosts();
                for (String host : hosts) {// 获取当前块在那台机器上
                    log.info(host);
                }
            }
            log.info("-------------------------");
        }
    }

    /**
     * 判断是文件还是文件夹
     */
    @Test
    public void testListStatus() throws IOException {
        FileStatus[] fileStatuses = fs.listStatus(new Path("/"));
        for (FileStatus fileStatus : fileStatuses) {
            String name = fileStatus.getPath().getName();
            log.info(name+"是文件:" + fileStatus.isFile());
            log.info(name+"是文件夹:" + fileStatus.isDirectory());
        }
    }

    @After
    public void after() throws IOException {
        if (fs != null) {
            fs.close();
            log.info("overs");
        }
    }

    private String getUUID() {
        return UUID.randomUUID().toString().replaceAll("-", "").toUpperCase(Locale.ROOT);
    }
}
